<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/11/7
 * Time: 16:29
 */

/**
 * 阿里短信2017-05-25版
 * 同一签名下
 * 同号码1分钟只能发送1次
 * 同号码1小时发送不超过5次
 * 同号码1自然日发送不超过10次
 * 超出限制频率Code返回SignatureDoesNotMatch
 * Class AliSms
 */
 
namespace app\api\service;
class AliSms {

    private $aliSmsUrl = 'http://dysmsapi.aliyuncs.com/'; //短信服务商请求地址
    private $accessKeyId = 'LTAIF3Yp3uYCPBKP';        //KeyId
    private $accessKeySecret = 'DrtrR6k81jVYIvDj98FFWWbbUyOIdb'; //KeySecret
    private $signName = '博学教育'; //短信签名

    /**
     * 短信运营商后台配置模板
     */
    const INFO_CHANGE_CODE = 'SMS_172955089'; //信息变更验证模板
    const CHANGE_PASSWORD_CODE = 'SMS_172955089'; //修改密码验证模板
    const USER_REGISTER_CDOE = 'SMS_172955089'; //用户注册验证模板
    const LOGIN_EXCEPTION_CODE = 'SMS_172955089'; //登录异常验证模板
    const LOGIN_CONFIRMATION_CODE = 'SMS_172955089'; //登录确认验证模板
    const AUTHENTICATION_CODE = 'SMS_172955089';   //身份验证验证模板
    const BIND_MOBILE_CODE = 'SMS_172955089';   //绑定手机号码模板
    const INTERNATIONAL_MOBILE_CODE = 'SMS_182682096';   //绑定手机号码模板

    /**
     * 短信接收号码
     **/
    private $phoneNumber;
    /**
     * 短信模板ID，传入的模板必须是在阿里大鱼“管理中心-短信模板管理”中的可用模板。示例：SMS_585014
     **/
    private $smsTemplateCode;
    /**
    * 短信模板变量，传参规则{"key":"value"}，key的名字须和申请模板中的变量名一致，多个变量之间以逗号隔开。示例：针对模板“验证码${code}，您正在进行${product}身份验证，打死不要告诉别人哦！”，传参时需传入{"code":"1234","product":"alidayu"}
	**/
	private $smsParam;

    public function setSmsParam($smsParam){
        $this->smsParam = $smsParam;
    }

    public function getSmsParam(){
        return $this->smsParam;
    }

    public function setPhoneNumber($phoneNumber){
        $this->phoneNumber = $phoneNumber;
    }

    public function getPhoneNumber(){
        return $this->phoneNumber;
    }

    public function setSmsTemplateCode($smsTemplateCode){
        $this->smsTemplateCode = $smsTemplateCode;
    }

    public function getSmsTemplateCode(){
        return $this->smsTemplateCode;
    }

    /**
     * 模板变量只有code时候参数处理
     * @param $mobileNum
     * @param $veriyCode
     * @param $templateCode
     */
    public function setTemplateParamOnlyCode($mobileNum,$veriyCode,$templateCode){
        $jsonStr = json_encode(array('code'=>$veriyCode)) ;
        $this->setSmsParam($jsonStr);
        $this->setPhoneNumber($mobileNum);
        $this->setSmsTemplateCode($templateCode);
    }

    /**
     * 单号码发送短信
     * @return array|bool
     */
    public function sendSms(){
        if(empty($this->phoneNumber) || empty( $this->smsParam) || empty ($this->smsTemplateCode)){
            return false;
        }
        
        date_default_timezone_set("GMT");
        $Timestamp = date('Y-m-d\TH:i:s\Z'); //固定格式
        $parameters = [
            'PhoneNumbers' => $this->phoneNumber,
            'SignName' => $this->signName,      //短信签名，阿里后台设置
            'TemplateCode' => $this->smsTemplateCode,   //短信模板，阿里后台设置
            'TemplateParam' => $this->smsParam, //短信模板变量替换JSON串
            'AccessKeyId' => $this->accessKeyId,
            'Action' => 'SendSms',    //固定值
            'Format' => 'JSON', // 格式JSON || XML
            'RegionId' => 'cn-hangzhou',    //固定节点cn-hangzhou公网值
            'SignatureMethod' => 'HMAC-SHA1',//建议固定值：HMAC-SHA1
            'SignatureVersion' => '1.0', //固定值
            'SignatureNonce' => uniqid(), //用于请求的防重放攻击
            'Timestamp' => $Timestamp,
            
            'Version' => '2017-05-25', //固定值
            'OutId' => '',         //外部流水扩展字段
        ];
        $Signature = $this->computeSignature($parameters, $this->accessKeySecret);
        $parameters['Signature'] = $Signature;
        $headers["x-sdk-client"] = "php/2.0.0"; //demo值
        return array('post_url'=> $this->aliSmsUrl,'params'=> $parameters,'headers'=> $headers);
    }

    /**
     * 数据签名
     * @param $parameters
     * @param $accessKeySecret
     * @return string
     */
    private function computeSignature($parameters, $accessKeySecret)
    {
        ksort($parameters);
        $canonicalizedQueryString = '';
        foreach($parameters as $key => $value)
        {
            $canonicalizedQueryString .= '&' . $this->percentEncode($key). '=' . $this->percentEncode($value);
        }
        $stringToSign = 'POST'.'&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
        $signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret."&", true));
        return $signature;
    }

    /**
     * 转换特殊字符
     * @param $str
     * @return null|string|string[]
     */
    private function percentEncode($str)
    {
        $res = urlencode($str);
        $res = preg_replace('/\+/', '%20', $res);
        $res = preg_replace('/\*/', '%2A', $res);
        $res = preg_replace('/%7E/', '~', $res);
        return $res;
    }




}